import Watcher from "./Watcher.js";
export default class Compile {
  constructor(el, vm) {
    this.el = el;
    this.vm = vm;
    this.fragment = null;
    this.init();
  }
  init() {
    if (this.el) {
      this.el = document.querySelector(this.el);
      this.fragment = this.node2fragment(this.el);
      this.compileElement(this.fragment);
      this.el.appendChild(this.fragment);
    } else {
      console.error("dom元素不存在");
    }
  }
  node2fragment(el) {
    const fragment = document.createDocumentFragment();
    let child = el.firstChild;
    while (child) {
      fragment.appendChild(child);
      child = el.firstChild;
    }
    return fragment;
  }
  compileElement(el) {
    const childNode = el.childNodes;
    if (!(childNode && childNode.length)) {
      return;
    }
    let reg = /\{\{(.*)\}\}/;
    Array.from(childNode).forEach(node => {
      let text = node.textContent;
      if (this.isNodeElement(node)) {
        this.compileNodeElement(node);
      } else if (this.isTextElement(node) && reg.test(text)) {
        this.compileNodeText(node, reg.exec(text)[1]);
      }
      this.compileElement(node);
    });
  }
  compileNodeElement(node) {
    const attrs = node.attributes;
    Array.from(attrs).forEach(attr => {
      const attrName = attr.name;
      const exp = attr.value;
      if (this.isDirective(attrName)) {
        const dir = attrName.substring(2);
        if (this.isEventHandle(dir)) {
          this.compileEvent(node, dir, exp);
        } else {
          this.compileDir(node, dir, exp);
        }
      }
      node.removeAttribute(attrName);
    });
  }
  // 解析事件
  compileEvent(node, dir, exp) {
    const eventType = dir.split(":")[1];
    const fn = this.vm.methods && this.vm.methods[exp];
    if (eventType && fn) {
      node.addEventListener(eventType, fn.bind(this.vm), false);
    }
  }
  // 解析指令
  compileDir(node, dir, exp) {
    if (dir === "model") {
      let value = this.vm.data[exp];
      this.updaterNode(node, value);
      new Watcher(this.vm, exp, val => {
        this.updaterNode(node, val);
      });
      node.addEventListener("input", e => {
        let newValue = e.target.value;
        if (newValue === value) return;
        value = newValue;
        // console.log(this.vm)
        this.vm.data[exp] = newValue;
      });
    }
  }
  // 解析text元素信息
  compileNodeText(node, exp) {
    const text = this.vm.data[exp];
    this.updaterText(node, text);
    new Watcher(this.vm, exp, val => {
      this.updaterText(node, val);
    });
  }
  updaterNode(node, value) {
    node.value = typeof value === "undefined" ? "" : value;
  }
  // 更新text文本
  updaterText(node, value) {
    node.textContent = typeof value === "undefined" ? "" : value;
  }
  // 是否为指令
  isDirective(attrName) {
    return attrName.indexOf("v-") === 0;
  }
  // 是否事件
  isEventHandle(dir) {
    return dir.indexOf("on:") === 0;
  }
  // 是否为node元素
  isNodeElement(node) {
    return node.nodeType === 1;
  }
  // 是否为text元素
  isTextElement(node) {
    return node.nodeType === 3;
  }
}
